Skip to content

Conversation

@dougfabris
Copy link
Member

@dougfabris dougfabris commented Sep 22, 2025

Proposed changes (including videos or screenshots)

Since our settings inputs already receive the hint prop, it makes sense to allow them to handle the FieldHint internally, allowing customization as needed

Issue(s)

Steps to test or reproduce

Further comments

CORE-1397

Summary by CodeRabbit

  • New Features

    • Settings inputs now accept and display contextual hints beneath fields across many input types (text, number, color, font, boolean, select, language, timezone, password, URL, room pick, lookup, multiselect, timespan, assets, and actions).
  • Style

    • Hints are rendered consistently by each input, providing a cleaner, more consistent admin settings UI.
    • Removed the separate hint wrapper; hints now appear inline with the relevant input for improved readability.

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Sep 22, 2025

Looks like this PR is ready to merge! 🎉
If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Sep 22, 2025

⚠️ No Changeset found

Latest commit: 0ef3469

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 22, 2025

Walkthrough

Adds a new optional hint prop to many admin setting input components and renders it via FieldHint; removes the FieldHint wrapper from MemoizedSetting while still passing hint down. ActionSettingInput now accepts and conditionally renders a hint.

Changes

Cohort / File(s) Summary of Changes
Settings inputs: add hint prop and FieldHint rendering
apps/meteor/client/views/admin/settings/Setting/inputs/AssetSettingInput.tsx, .../BooleanSettingInput.tsx, .../ColorSettingInput.tsx, .../FontSettingInput.tsx, .../GenericSettingInput.tsx, .../IntSettingInput.tsx, .../LanguageSettingInput.tsx, .../LookupSettingInput.tsx, .../MultiSelectSettingInput.tsx, .../PasswordSettingInput.tsx, .../RelativeUrlSettingInput.tsx, .../RoomPickSettingInput.tsx, .../SelectSettingInput.tsx, .../SelectTimezoneSettingInput.tsx, .../StringSettingInput.tsx, .../TimespanSettingInput.tsx
Import FieldHint and accept an optional hint prop; conditionally render <FieldHint>{hint}</FieldHint> after inputs. Most components’ public props now include hint (types inferred/adjusted); UI-only change.
Action setting input: hint support
apps/meteor/client/views/admin/settings/Setting/inputs/ActionSettingInput.tsx
Extends props to accept hint (ReactNode) and conditionally renders FieldHint alongside the existing Saved hint.
Memoized setting: remove wrapper FieldHint
apps/meteor/client/views/admin/settings/Setting/MemoizedSetting.tsx
Removes FieldHint import and wrapper rendering while continuing to pass hint through to child input components.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Admin as Admin User
  participant MS as MemoizedSetting
  participant SI as SettingInput
  participant FH as FieldHint

  Admin->>MS: Open setting panel
  MS->>SI: Render input with props (..., hint)
  alt hint provided
    SI->>FH: Render FieldHint with hint content
    FH-->>SI: Displayed under input
  else no hint
    SI-->>Admin: Input rendered without FieldHint
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

stat: ready to merge, stat: QA assured

Poem

I nibble keys and hop and sing,
Hints now bloom beneath each thing.
One wrapper jumped and left the trail,
But whispers follow without fail.
A rabbit thumbs up—settings prevail 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "refactor: Allow setting's hint customization" is concise and accurately reflects the primary change: refactoring settings inputs to support customizable hints via the existing hint prop; it is specific and aligned with the diff's focus on hint propagation and FieldHint usage.
Linked Issues Check ✅ Passed The changes update most settings input components to accept a hint prop and render FieldHint internally while moving wrapper-level hint rendering out of MemoizedSetting, which implements the intent of CORE-1397 to allow setting hint customization; the file summaries show coding changes focused on hint propagation with no deviations from that objective.
Out of Scope Changes Check ✅ Passed I reviewed the summaries and found the modifications are cohesive and limited to hint handling (adding hint props, importing and rendering FieldHint in inputs, and removing wrapper-level FieldHint); there are no unrelated feature or behavioral changes introduced by this PR.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/setting-hint

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a07fc4c and 6a8aa75.

📒 Files selected for processing (1)
  • apps/meteor/client/views/admin/settings/Setting/inputs/ActionSettingInput.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/meteor/client/views/admin/settings/Setting/inputs/ActionSettingInput.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Sep 22, 2025

Codecov Report

❌ Patch coverage is 50.90909% with 27 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.30%. Comparing base (3b2905b) to head (0ef3469).

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #37032      +/-   ##
===========================================
- Coverage    67.31%   67.30%   -0.02%     
===========================================
  Files         3337     3337              
  Lines       113294   113326      +32     
  Branches     20562    20577      +15     
===========================================
+ Hits         76266    76269       +3     
- Misses       34422    34445      +23     
- Partials      2606     2612       +6     
Flag Coverage Δ
e2e 57.02% <23.52%> (-0.01%) ⬇️
unit 71.12% <45.45%> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dougfabris dougfabris added this to the 7.11.0 milestone Sep 23, 2025
@dougfabris dougfabris marked this pull request as ready for review September 23, 2025 14:03
@dougfabris dougfabris requested a review from a team as a code owner September 23, 2025 14:03
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/meteor/client/views/admin/settings/Setting/inputs/AssetSettingInput.tsx (1)

120-124: Fix accept attribute when no extensions are provided

Current template emits ".undefined" when fileConstraints or extensions are absent, unintentionally restricting uploads.

-								<input type='file' accept={`.${fileConstraints?.extensions?.join(', .')}`} onChange={handleUpload} disabled={disabled} />
+								<input
+									type='file'
+									accept={fileConstraints?.extensions?.length ? `.${fileConstraints?.extensions?.join(', .')}` : undefined}
+									onChange={handleUpload}
+									disabled={disabled}
+								/>
apps/meteor/client/views/admin/settings/Setting/inputs/StringSettingInput.tsx (1)

7-11: Change SettingInputProps.hint to ReactNode

SettingInputProps currently declares hint?: string — update it to hint?: ReactNode to match consumers that pass React nodes (file: apps/meteor/client/views/admin/settings/Setting/inputs/types.ts; change hint?: string;hint?: ReactNode;).

🧹 Nitpick comments (11)
apps/meteor/client/views/admin/settings/Setting/inputs/MultiSelectSettingInput.tsx (1)

18-59: Add aria-describedby to associate the hint with the input (accessibility).

Link the hint to the control so screen readers announce it.

 function MultiSelectSettingInput({
   _id,
   label,
   value,
-  hint,
+  hint,
   placeholder,
   readonly,
   disabled,
   required,
   values = [],
   hasResetButton,
   onChangeValue,
   onResetButtonClick,
   autocomplete,
 }: MultiSelectSettingInputProps): ReactElement {
   const { t } = useTranslation();
 
   const handleChange = (value: string[]): void => {
     onChangeValue?.(value);
     // onChangeValue && onChangeValue([...event.currentTarget.querySelectorAll('option')].filter((e) => e.selected).map((el) => el.value));
   };
   const Component = autocomplete ? MultiSelectFiltered : MultiSelect;
+  const hintId = `${_id}-hint`;
   return (
     <Field>
       <FieldRow>
         <FieldLabel htmlFor={_id} title={_id} required={required}>
           {label}
         </FieldLabel>
         {hasResetButton && <ResetSettingButton data-qa-reset-setting-id={_id} onClick={onResetButtonClick} />}
       </FieldRow>
       <FieldRow>
         <Component
           max-width='full'
           data-qa-setting-id={_id}
           id={_id}
           value={value}
           placeholder={placeholder}
           disabled={disabled}
           readOnly={readonly}
           // autoComplete={autocomplete === false ? 'off' : undefined}
           onChange={handleChange}
           options={values.map(({ key, i18nLabel }) => [key, t(i18nLabel)])}
+          aria-describedby={hint ? hintId : undefined}
         />
       </FieldRow>
-      {hint && <FieldHint>{hint}</FieldHint>}
+      {hint && <FieldHint id={hintId}>{hint}</FieldHint>}
     </Field>
   );
 }
apps/meteor/client/views/admin/settings/Setting/inputs/PasswordSettingInput.tsx (1)

13-48: Add aria-describedby to associate the hint with the input (accessibility).

Ensure assistive tech reads the hint when focusing the password field.

 function PasswordSettingInput({
   _id,
   label,
   value,
-  hint,
+  hint,
   placeholder,
   readonly,
   autocomplete,
   disabled,
   required,
   hasResetButton,
   onChangeValue,
   onResetButtonClick,
 }: PasswordSettingInputProps): ReactElement {
   const handleChange: EventHandler<SyntheticEvent<HTMLInputElement>> = (event) => {
     onChangeValue?.(event.currentTarget.value);
   };
 
   return (
     <Field>
       <FieldRow>
         <FieldLabel htmlFor={_id} title={_id} required={required}>
           {label}
         </FieldLabel>
         {hasResetButton && <ResetSettingButton data-qa-reset-setting-id={_id} onClick={onResetButtonClick} />}
       </FieldRow>
       <FieldRow>
         <PasswordInput
           data-qa-setting-id={_id}
           id={_id}
           value={value}
           placeholder={placeholder}
           disabled={disabled}
           readOnly={readonly}
           autoComplete={autocomplete === false ? 'new-password' : undefined}
           onChange={handleChange}
+          aria-describedby={hint ? `${_id}-hint` : undefined}
         />
       </FieldRow>
-      {hint && <FieldHint>{hint}</FieldHint>}
+      {hint && <FieldHint id={`${_id}-hint`}>{hint}</FieldHint>}
     </Field>
   );
 }
apps/meteor/client/views/admin/settings/Setting/MemoizedSetting.tsx (1)

90-101: Optional: tighten typing for InputComponent props to include hint.

inputsByType uses ElementType, so TS won’t catch missing hint support. Consider a shared prop interface with hint?: ReactNode to improve safety.

apps/meteor/client/views/admin/settings/Setting/inputs/ColorSettingInput.tsx (1)

21-104: Add aria-describedby to associate the hint with the input(s) (accessibility).

Apply to both editor modes and the trailing FieldHint.

 function ColorSettingInput({
   _id,
   label,
   value,
-  hint,
+  hint,
   editor,
   allowedTypes = [],
   placeholder,
   readonly,
   autocomplete,
   disabled,
   required,
   hasResetButton,
   onChangeValue,
   onChangeEditor,
   onResetButtonClick,
 }: ColorSettingInputProps): ReactElement {
   const { t } = useTranslation();
+  const hintId = `${_id}-hint`;
 
 ...
-              {editor === 'color' && (
+              {editor === 'color' && (
                 <InputBox
                   data-qa-setting-id={_id}
                   type='color'
                   id={_id}
                   value={value}
                   placeholder={placeholder}
                   disabled={disabled}
                   readOnly={readonly}
                   autoComplete={autocomplete === false ? 'off' : undefined}
                   onChange={handleChange}
+                  aria-describedby={hint ? hintId : undefined}
                 />
               )}
-              {editor === 'expression' && (
+              {editor === 'expression' && (
                 <TextInput
                   data-qa-setting-id={_id}
                   id={_id}
                   value={value}
                   placeholder={placeholder}
                   disabled={disabled}
                   readOnly={readonly}
                   autoComplete={autocomplete === false ? 'off' : undefined}
                   onChange={handleChange}
+                  aria-describedby={hint ? hintId : undefined}
                 />
               )}
 ...
-      {hint && <FieldHint>{hint}</FieldHint>}
+      {hint && <FieldHint id={hintId}>{hint}</FieldHint>}
apps/meteor/client/views/admin/settings/Setting/inputs/LanguageSettingInput.tsx (1)

14-52: Add aria-describedby to associate the hint with the select (accessibility).

 function LanguageSettingInput({
   _id,
   label,
   value,
-  hint,
+  hint,
   placeholder,
   readonly,
   autocomplete,
   disabled,
   required,
   hasResetButton,
   onChangeValue,
   onResetButtonClick,
 }: LanguageSettingInputProps): ReactElement {
   const languages = useLanguages();
+  const hintId = `${_id}-hint`;
 ...
         <Select
           data-qa-setting-id={_id}
           id={_id}
           value={value}
           placeholder={placeholder}
           disabled={disabled}
           readOnly={readonly}
           autoComplete={autocomplete === false ? 'off' : undefined}
           onChange={(value) => handleChange(String(value))}
           options={languages.map(({ key, name }) => [key, name])}
+          aria-describedby={hint ? hintId : undefined}
         />
       </FieldRow>
-      {hint && <FieldHint>{hint}</FieldHint>}
+      {hint && <FieldHint id={hintId}>{hint}</FieldHint>}
apps/meteor/client/views/admin/settings/Setting/inputs/LookupSettingInput.tsx (1)

19-65: Add aria-describedby to associate the hint with the select (accessibility).

 function LookupSettingInput({
   _id,
   label,
   value,
-  hint,
+  hint,
   placeholder,
   readonly,
   autocomplete,
   disabled,
   required,
   lookupEndpoint,
   hasResetButton,
   onChangeValue,
   onResetButtonClick,
 }: LookupSettingInputProps): ReactElement {
+  const hintId = `${_id}-hint`;
 ...
         <Select
           data-qa-setting-id={_id}
           id={_id}
           value={value}
           placeholder={placeholder}
           disabled={disabled}
           readOnly={readonly}
           autoComplete={autocomplete === false ? 'off' : undefined}
           onChange={(value) => handleChange(String(value))}
           options={values.map(({ key, label }) => [key, label])}
+          aria-describedby={hint ? hintId : undefined}
         />
       </FieldRow>
-      {hint && <FieldHint>{hint}</FieldHint>}
+      {hint && <FieldHint id={hintId}>{hint}</FieldHint>}
apps/meteor/client/views/admin/settings/Setting/inputs/SelectTimezoneSettingInput.tsx (1)

14-50: Add aria-describedby to associate the hint with the select (accessibility).

 function SelectTimezoneSettingInput({
   _id,
   label,
   value,
-  hint,
+  hint,
   placeholder,
   readonly,
   autocomplete,
   disabled,
   required,
   hasResetButton,
   onChangeValue,
   onResetButtonClick,
 }: SelectTimezoneSettingInputProps): ReactElement {
   const handleChange = (value: string): void => {
     onChangeValue?.(value);
   };
+  const hintId = `${_id}-hint`;
 ...
         <Select
           data-qa-setting-id={_id}
           id={_id}
           value={value}
           placeholder={placeholder}
           disabled={disabled}
           readOnly={readonly}
           autoComplete={autocomplete === false ? 'off' : undefined}
           onChange={(value) => handleChange(String(value))}
           options={moment.tz.names().map((key) => [key, key])}
+          aria-describedby={hint ? hintId : undefined}
         />
       </FieldRow>
-      {hint && <FieldHint>{hint}</FieldHint>}
+      {hint && <FieldHint id={hintId}>{hint}</FieldHint>}
apps/meteor/client/views/admin/settings/Setting/inputs/RoomPickSettingInput.tsx (1)

15-51: Add aria-describedby to associate the hint with the autocomplete (accessibility).

If RoomAutoCompleteMultiple forwards aria-* props, wire it to the hint.

 function RoomPickSettingInput({
   _id,
   label,
   value,
-  hint,
+  hint,
   placeholder,
   readonly,
   disabled,
   required,
   hasResetButton,
   onChangeValue,
   onResetButtonClick,
 }: RoomPickSettingInputProps): ReactElement {
   const parsedValue = (value || []).map(({ _id }) => _id);
+  const hintId = `${_id}-hint`;
 ...
         <RoomAutoCompleteMultiple
           readOnly={readonly}
           placeholder={placeholder}
           disabled={disabled}
           value={parsedValue}
           onChange={handleChange}
+          aria-describedby={hint ? hintId : undefined}
         />
       </FieldRow>
-      {hint && <FieldHint>{hint}</FieldHint>}
+      {hint && <FieldHint id={hintId}>{hint}</FieldHint>}
apps/meteor/client/views/admin/settings/Setting/inputs/StringSettingInput.tsx (1)

44-56: Link hint to inputs via aria-describedby for better a11y

Associate FieldHint to the input/textarea so screen readers announce it.

 					<TextAreaInput
 						data-qa-setting-id={_id}
 						id={_id}
 						name={name}
 						rows={4}
 						value={value}
 						placeholder={placeholder}
 						disabled={disabled}
 						readOnly={readonly}
 						error={error}
 						autoComplete={autocomplete === false ? 'off' : undefined}
+						aria-describedby={hint ? `${_id}-hint` : undefined}
 						onChange={handleChange}
 					/>
...
 					<TextInput
 						data-qa-setting-id={_id}
 						id={_id}
 						value={value}
 						name={name}
 						placeholder={placeholder}
 						disabled={disabled}
 						readOnly={readonly}
 						autoComplete={autocomplete === false ? 'off' : undefined}
 						error={error}
+						aria-describedby={hint ? `${_id}-hint` : undefined}
 						onChange={handleChange}
 					/>
...
-			{hint && <FieldHint>{hint}</FieldHint>}
+			{hint && <FieldHint id={`${_id}-hint`}>{hint}</FieldHint>}

Also applies to: 58-69, 72-73

apps/meteor/client/views/admin/settings/Setting/inputs/ActionSettingInput.tsx (1)

35-41: A11y: associate hints with the control via aria-describedby

Improve screen-reader experience by linking the hints to the button.

Apply within the changed range:

-      {hint && <FieldHint>{hint}</FieldHint>}
+      {hint && <FieldHint id={`${_id}-hint`}>{hint}</FieldHint>}

Apply outside the changed range (illustrative TSX snippet):

// before return (inside component)
const describedBy =
	[
		sectionChanged ? `${_id}-sectionChanged-hint` : undefined,
		hint ? `${_id}-hint` : undefined,
	].filter(Boolean).join(' ') || undefined;

// in JSX
<Button
	data-qa-setting-id={_id}
	disabled={disabled || sectionChanged}
	primary
	onClick={handleClick}
	aria-describedby={describedBy}
>
	{t(actionText)}
</Button>

{sectionChanged && <FieldHint id={`${_id}-sectionChanged-hint`}>{t('Save_to_enable_this_action')}</FieldHint>}
apps/meteor/client/views/admin/settings/Setting/inputs/FontSettingInput.tsx (1)

49-49: A11y: link hint to input via aria-describedby

Associate the hint with the input for screen readers.

Apply within the changed range:

-      {hint && <FieldHint>{hint}</FieldHint>}
+      {hint && <FieldHint id={`${_id}-hint`}>{hint}</FieldHint>}

Apply outside the changed range (illustrative TSX snippet):

// before return (inside component)
const describedBy = hint ? `${_id}-hint` : undefined;

// on TextInput
<TextInput
  ...
  aria-describedby={describedBy}
/>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 24fba8d and a07fc4c.

📒 Files selected for processing (18)
  • apps/meteor/client/views/admin/settings/Setting/MemoizedSetting.tsx (1 hunks)
  • apps/meteor/client/views/admin/settings/Setting/inputs/ActionSettingInput.tsx (2 hunks)
  • apps/meteor/client/views/admin/settings/Setting/inputs/AssetSettingInput.tsx (3 hunks)
  • apps/meteor/client/views/admin/settings/Setting/inputs/BooleanSettingInput.tsx (3 hunks)
  • apps/meteor/client/views/admin/settings/Setting/inputs/ColorSettingInput.tsx (2 hunks)
  • apps/meteor/client/views/admin/settings/Setting/inputs/FontSettingInput.tsx (3 hunks)
  • apps/meteor/client/views/admin/settings/Setting/inputs/GenericSettingInput.tsx (3 hunks)
  • apps/meteor/client/views/admin/settings/Setting/inputs/IntSettingInput.tsx (3 hunks)
  • apps/meteor/client/views/admin/settings/Setting/inputs/LanguageSettingInput.tsx (3 hunks)
  • apps/meteor/client/views/admin/settings/Setting/inputs/LookupSettingInput.tsx (3 hunks)
  • apps/meteor/client/views/admin/settings/Setting/inputs/MultiSelectSettingInput.tsx (3 hunks)
  • apps/meteor/client/views/admin/settings/Setting/inputs/PasswordSettingInput.tsx (3 hunks)
  • apps/meteor/client/views/admin/settings/Setting/inputs/RelativeUrlSettingInput.tsx (3 hunks)
  • apps/meteor/client/views/admin/settings/Setting/inputs/RoomPickSettingInput.tsx (3 hunks)
  • apps/meteor/client/views/admin/settings/Setting/inputs/SelectSettingInput.tsx (3 hunks)
  • apps/meteor/client/views/admin/settings/Setting/inputs/SelectTimezoneSettingInput.tsx (3 hunks)
  • apps/meteor/client/views/admin/settings/Setting/inputs/StringSettingInput.tsx (3 hunks)
  • apps/meteor/client/views/admin/settings/Setting/inputs/TimespanSettingInput.tsx (3 hunks)
🔇 Additional comments (11)
apps/meteor/client/views/admin/settings/Setting/MemoizedSetting.tsx (1)

90-101: All InputComponents render the hint prop.
Confirmed: every input referenced by MemoizedSetting renders FieldHint (checked apps/meteor/client/views/admin/settings/Setting/inputs).

apps/meteor/client/views/admin/settings/Setting/inputs/IntSettingInput.tsx (1)

38-49: Add aria-describedby to tie FieldHint to the input (duplicate of StringSettingInput)

This improves screen reader support.

 				<InputBox
 					data-qa-setting-id={_id}
 					id={_id}
 					type='number'
 					value={value}
 					placeholder={placeholder}
 					disabled={disabled}
 					readOnly={readonly}
 					autoComplete={autocomplete === false ? 'off' : undefined}
+					aria-describedby={hint ? `${_id}-hint` : undefined}
 					onChange={handleChange}
 				/>
...
-			{hint && <FieldHint>{hint}</FieldHint>}
+			{hint && <FieldHint id={`${_id}-hint`}>{hint}</FieldHint>}

Also applies to: 50-51

apps/meteor/client/views/admin/settings/Setting/inputs/GenericSettingInput.tsx (1)

38-47: Add aria-describedby to tie FieldHint to the input (duplicate of StringSettingInput)

Aligns a11y behavior across inputs.

 				<TextInput
 					data-qa-setting-id={_id}
 					id={_id}
 					value={value}
 					placeholder={placeholder}
 					disabled={disabled}
 					readOnly={readonly}
 					autoComplete={autocomplete === false ? 'off' : undefined}
+					aria-describedby={hint ? `${_id}-hint` : undefined}
 					onChange={handleChange}
 				/>
...
-			{hint && <FieldHint>{hint}</FieldHint>}
+			{hint && <FieldHint id={`${_id}-hint`}>{hint}</FieldHint>}

Also applies to: 49-50

apps/meteor/client/views/admin/settings/Setting/inputs/SelectSettingInput.tsx (2)

43-53: Add aria-describedby to tie FieldHint to the select (duplicate of StringSettingInput)

Improves hint discoverability for assistive tech.

 				<Select
 					data-qa-setting-id={_id}
 					id={_id}
 					value={value}
 					placeholder={placeholder}
 					disabled={disabled}
 					readOnly={readonly}
 					autoComplete={autocomplete === false ? 'off' : undefined}
+					aria-describedby={hint ? `${_id}-hint` : undefined}
 					onChange={(value) => handleChange(String(value))}
 					options={values.map(({ key, i18nLabel }) => [key, t(i18nLabel)])}
 				/>
...
-			{hint && <FieldHint>{hint}</FieldHint>}
+			{hint && <FieldHint id={`${_id}-hint`}>{hint}</FieldHint>}

Also applies to: 55-56


17-27: Resolved — MemoizedSetting forwards hint and no longer renders FieldHint; inputs render their own hint MemoizedSetting passes hint down to InputComponent and does not render FieldHint; each input in apps/meteor/client/views/admin/settings/Setting/inputs accepts a hint prop and renders FieldHint, so no duplicate hint rendering.

apps/meteor/client/views/admin/settings/Setting/inputs/AssetSettingInput.tsx (1)

120-124: Add aria-describedby to tie FieldHint to the file input (duplicate of StringSettingInput)

Improves a11y for the upload control.

-								<input type='file' accept={`.${fileConstraints?.extensions?.join(', .')}`} onChange={handleUpload} disabled={disabled} />
+								<input
+									type='file'
+									accept={fileConstraints?.extensions?.length ? `.${fileConstraints?.extensions?.join(', .')}` : undefined}
+									onChange={handleUpload}
+									disabled={disabled}
+									aria-describedby={hint ? `${_id}-hint` : undefined}
+								/>
...
-			{hint && <FieldHint>{hint}</FieldHint>}
+			{hint && <FieldHint id={`${_id}-hint`}>{hint}</FieldHint>}

Also applies to: 128-129

apps/meteor/client/views/admin/settings/Setting/inputs/TimespanSettingInput.tsx (1)

94-104: Add aria-describedby to tie FieldHint to both inputs (duplicate of StringSettingInput)

Covers number input and unit select.

 				<InputBox
 					data-qa-setting-id={_id}
 					id={_id}
 					type='number'
 					value={internalValue}
 					placeholder={placeholder}
 					disabled={disabled}
 					readOnly={readonly}
 					autoComplete={autocomplete === false ? 'off' : undefined}
+					aria-describedby={hint ? `${_id}-hint` : undefined}
 					onChange={handleChange}
 				/>
 			</FieldRow>
 			<FieldRow>
-				<Select value={timeUnit} disabled={disabled} options={timeUnitOptions} onChange={handleChangeTimeUnit} />
+				<Select
+					value={timeUnit}
+					disabled={disabled}
+					options={timeUnitOptions}
+					onChange={handleChangeTimeUnit}
+					aria-describedby={hint ? `${_id}-hint` : undefined}
+				/>
 			</FieldRow>
-			{hint && <FieldHint>{hint}</FieldHint>}
+			{hint && <FieldHint id={`${_id}-hint`}>{hint}</FieldHint>}

Also applies to: 107-108, 109-110

apps/meteor/client/views/admin/settings/Setting/inputs/BooleanSettingInput.tsx (1)

34-41: Add aria-describedby to tie FieldHint to the ToggleSwitch (duplicate of StringSettingInput)

Improves screen reader output.

 					<ToggleSwitch
 						data-qa-setting-id={_id}
 						id={_id}
 						checked={value === true}
 						disabled={disabled || readonly}
+						aria-describedby={hint ? `${_id}-hint` : undefined}
 						onChange={handleChange}
 					/>
...
-			{hint && <FieldHint>{hint}</FieldHint>}
+			{hint && <FieldHint id={`${_id}-hint`}>{hint}</FieldHint>}

Also applies to: 43-44

apps/meteor/client/views/admin/settings/Setting/inputs/RelativeUrlSettingInput.tsx (1)

38-47: Add aria-describedby to tie FieldHint to the UrlInput (duplicate of StringSettingInput)

Helps assistive tech announce the hint.

 			<UrlInput
 				data-qa-setting-id={_id}
 				id={_id}
 				value={getAbsoluteUrl(value || '')}
 				placeholder={placeholder}
 				disabled={disabled}
 				readOnly={readonly}
 				autoComplete={autocomplete === false ? 'off' : undefined}
+				aria-describedby={hint ? `${_id}-hint` : undefined}
 				onChange={handleChange}
 			/>
-			{hint && <FieldHint>{hint}</FieldHint>}
+			{hint && <FieldHint id={`${_id}-hint`}>{hint}</FieldHint>}

Also applies to: 48-49

apps/meteor/client/views/admin/settings/Setting/inputs/ActionSettingInput.tsx (1)

12-16: Prop added + rendering LGTM

Accepting hint?: ReactNode and rendering it via FieldHint is consistent with the new API and keeps the existing “save to enable” hint intact.

Also applies to: 41-41

apps/meteor/client/views/admin/settings/Setting/inputs/FontSettingInput.tsx (1)

1-1: Hint rendering LGTM

Adding FieldHint and wiring it to the existing hint prop matches the new pattern.

Also applies to: 49-49

Copy link
Member

@MartinSchoeler MartinSchoeler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NVM I forgot that we provide the setting key as an ID on the tooltips

@MartinSchoeler MartinSchoeler added the stat: QA assured Means it has been tested and approved by a company insider label Sep 23, 2025
@dionisio-bot dionisio-bot bot added the stat: ready to merge PR tested and approved waiting for merge label Sep 23, 2025
@kodiakhq kodiakhq bot merged commit 65b57cc into develop Sep 24, 2025
49 checks passed
@kodiakhq kodiakhq bot deleted the refactor/setting-hint branch September 24, 2025 17:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stat: QA assured Means it has been tested and approved by a company insider stat: ready to merge PR tested and approved waiting for merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants